/**	@file Substitution.h
 *	@brief Substitution functions. */
#ifndef Substitution_h_majdo_sympy_cpp
#define Substitution_h_majdo_sympy_cpp
#include <vector>
#include "Ex.h"
#include "Number.h"
namespace sympycpp {
class Pow;
class Mul;
class Add;
class Fx;
/**	@class Substitution 
 * 	@brief Covering of substitutiton.
 * 	@todo Substitution are not effective (slow) => redesign it.*/
class Substitution{
public :
	/**	@brief Substitution of an expression by another expression.
	 * 	@param originalExp is a changed expression 
	 * 	@param fromEx is a replaced expression
	 * 	@param toEx is a repalcing expression*/
	static void sub(Ex * & originalEx, const Ex * fromEx, const Ex * toEx);
	/**	@brief Substitution of an expression by another expression.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression 
	 * 	@param fromEx is a replaced expression
	 * 	@param toEx is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
static bool sub2(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
private :
	Substitution() {}
	/**	@brief Substitution of an expression by another expression in an addition.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (addition)
	 * 	@param fromEx is a replaced expression
	 * 	@param toEx is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInAdd(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Substitution of an addition  by expression in an addition.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (addition)
	 * 	@param fromEx is a replaced expression (addition)
	 * 	@param toEx is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static void subAddInAdd(Ex * & originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio, const Sign sameSign, const Number & replacedMultiplicity);
	/**	@brief Detection of subexpressions (elements of an addition) in another addition.
	 *	@param originalExp is the addition where are searched subexpressions 
	 *	@param searchedExp is the addition which addends are searched subexpressions
	 *	@param sign relations of subexpressions for deleting*/
	static bool isAddInAdd(const Add * originalExp, const Add * searchedExp, Sign & sign);
	/**	@brief Substitution of an expression by another expression in an multiple expression.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (multiple expression)
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInMultiple(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Substitution of an expression by another expression in an multiplication.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (multiplication)
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInMul(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Detection of subexpressions (elements of an multiplication) in another multiplication.
	 *	@param originalExp is the multiplication where are searched subexpressions 
	 *	@param searchedExp is the multiplication which multiplicands are searched subexpressions
	 *	@param sign relations of subexpressions for deleting*/
	static bool isMulInMul(const Mul * originalExp, const Mul * searchedExp, Sign & sign);
	/**	@brief Substitution in multiplication.
	 * 	Auxiliary function that makes deleting and move of multiplicands..
	 *	@see substituteInMul() is a function that makes the substitution in a multiplication.*/
	static void subInMul(Ex * & originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio, const Sign sameSign);
	/**	@brief Substitution of an expression by another expression.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (number)
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInNum(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Substitution of an expression by another expression.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (variable)
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInSym(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Substitution of an expression by another expression in a power.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (power)
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInPow(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Substitution of an expression by another expression in a functions.
	 * 	@warning The replaced and replacing expression can not be multiple. 
	 * 	The multiplicity of these expression is represented as a ratio of their multiplicities.
	 * 	@param originalExp is a changed expression (functions)
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions*/
	static bool substituteInFx(Ex * &  originalExp, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio);
	/**	@brief Sequential subsittution.
	 * 	@param Exs is container that contains changed expressions 	
	 * 	@param replacedExp is a replaced expression
	 * 	@param proxyExp is a repalcing expression
	 * 	@param ratio is ratio of multiplicity of replace & repalcing expressions
	 * 	@param indEx changed expression*/
	static bool subInside(basic_container &  Exs, const Ex * replacedExp,const Ex * proxyExp, const Number * ratio, iterator & indEx);
	///	@brief Simple construction of multiple expressions.
	static void MultiplicityMaker(Number * & ratio, Ex * & Expression, const allocationPolicy policy);
};
}
#endif
